<?php
/**
 * API文档解析器
 * 用于解析控制器方法的DocBlock注释，提取API参数、返回值等详细信息
 */

namespace app\common;

/**
 * API文档解析器类
 */
class ApiDocParser {
    /**
     * 解析控制器方法的DocBlock注释
     * @param string $controllerFile 控制器文件路径
     * @param string $methodName 方法名称
     * @return array 解析结果
     */
    public static function parseMethodDoc($controllerFile, $methodName) {
        if (!is_file($controllerFile)) {
            return [];
        }
        
        $content = file_get_contents($controllerFile);
        $docBlock = self::extractMethodDocBlock($content, $methodName);
        
        if (empty($docBlock)) {
            return [];
        }
        
        return [
            'description' => self::parseDescription($docBlock),
            'params' => self::parseParams($docBlock),
            'query_params' => self::parseQueryParams($docBlock),
            'body_params' => self::parseBodyParams($docBlock),
            'return' => self::parseReturn($docBlock),
            'examples' => self::parseExamples($docBlock),
            'headers' => self::parseHeaders($docBlock),
            'validate' => self::parseValidate($docBlock),
            'author' => self::parseAuthor($docBlock),
            'since' => self::parseSince($docBlock)
        ];
    }
    
    /**
     * 从控制器文件内容中提取方法的DocBlock注释
     * @param string $content 文件内容
     * @param string $methodName 方法名称
     * @return string 注释内容
     */
    protected static function extractMethodDocBlock($content, $methodName) {
        $pattern = '/\/\*\*\s*(?:\*[^\n]*\n)*?\*\/\s*public\s+(?:static\s+)?function\s+' . preg_quote($methodName) . '\s*\(/s';
        
        if (preg_match($pattern, $content, $matches)) {
            $fullMatch = $matches[0];
            
            // 提取DocBlock部分
            if (preg_match('/\/\*\*\s*(.*?)\s*\*\//s', $fullMatch, $docMatches)) {
                return $docMatches[1];
            }
        }
        
        return '';
    }
    
    /**
     * 解析方法描述
     * @param string $docBlock 文档块
     * @return string 描述内容
     */
    protected static function parseDescription($docBlock) {
        // 移除@tags之前的内容作为描述
        $pattern = '/^(.*?)@\w+/s';
        if (preg_match($pattern, $docBlock, $matches)) {
            $description = $matches[1];
        } else {
            $description = $docBlock;
        }
        
        // 清理描述内容
        $description = str_replace('*', '', $description);
        $description = trim(preg_replace('/\s+/', ' ', $description));
        
        return $description;
    }
    
    /**
     * 解析@param标签
     * @param string $docBlock 文档块
     * @return array 参数列表
     */
    protected static function parseParams($docBlock) {
        $params = [];
        $pattern = '/@param\s+(\S+)\s+(\$\w+)\s*(.*?)(?=\*\s*@|\*\/)/s';
        
        if (preg_match_all($pattern, $docBlock, $matches, PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                $paramInfo = self::parseParamDetails($match[3]);
                
                $params[] = [
                    'name' => ltrim($match[2], '$'),
                    'type' => $match[1],
                    'description' => $paramInfo['description'],
                    'required' => $paramInfo['required'],
                    'default' => $paramInfo['default'],
                    'example' => $paramInfo['example']
                ];
            }
        }
        
        return $params;
    }
    
    /**
     * 解析参数详情（必填、默认值、示例等）
     * @param string $paramDesc 参数描述
     * @return array 参数详情
     */
    protected static function parseParamDetails($paramDesc) {
        $details = [
            'description' => trim($paramDesc),
            'required' => true,
            'default' => null,
            'example' => null
        ];
        
        // 检查是否为可选参数
        if (stripos($paramDesc, '可选') !== false || 
            stripos($paramDesc, 'optional') !== false ||
            stripos($paramDesc, '选填') !== false) {
            $details['required'] = false;
        }
        
        // 检查默认值
        if (preg_match('/默认值[:：]\s*([^,\n]+)/i', $paramDesc, $defaultMatch)) {
            $details['default'] = trim($defaultMatch[1]);
        }
        
        // 检查示例
        if (preg_match('/示例[:：]\s*([^,\n]+)/i', $paramDesc, $exampleMatch)) {
            $details['example'] = trim($exampleMatch[1]);
        }
        
        return $details;
    }
    
    /**
     * 解析@queryParam标签（URL查询参数）
     * @param string $docBlock 文档块
     * @return array 查询参数列表
     */
    protected static function parseQueryParams($docBlock) {
        $params = [];
        $pattern = '/@queryParam\s+(\S+)\s+(\w+)\s*(.*?)(?=\*\s*@|\*\/)/s';
        
        if (preg_match_all($pattern, $docBlock, $matches, PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                $paramInfo = self::parseParamDetails($match[3]);
                
                $params[] = [
                    'name' => $match[2],
                    'type' => $match[1],
                    'description' => $paramInfo['description'],
                    'required' => $paramInfo['required'],
                    'default' => $paramInfo['default'],
                    'example' => $paramInfo['example']
                ];
            }
        }
        
        return $params;
    }
    
    /**
     * 解析@bodyParam标签（请求体参数）
     * @param string $docBlock 文档块
     * @return array 请求体参数列表
     */
    protected static function parseBodyParams($docBlock) {
        $params = [];
        $pattern = '/@bodyParam\s+(\S+)\s+(\w+)\s*(.*?)(?=\*\s*@|\*\/)/s';
        
        if (preg_match_all($pattern, $docBlock, $matches, PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                $paramInfo = self::parseParamDetails($match[3]);
                
                $params[] = [
                    'name' => $match[2],
                    'type' => $match[1],
                    'description' => $paramInfo['description'],
                    'required' => $paramInfo['required'],
                    'default' => $paramInfo['default'],
                    'example' => $paramInfo['example']
                ];
            }
        }
        
        return $params;
    }
    
    /**
     * 解析@return标签
     * @param string $docBlock 文档块
     * @return array 返回值信息
     */
    protected static function parseReturn($docBlock) {
        $return = [
            'type' => '',
            'description' => '',
            'structure' => null
        ];
        
        $pattern = '/@return\s+(\S+)\s*(.*?)(?=\*\s*@|\*\/)/s';
        
        if (preg_match($pattern, $docBlock, $matches)) {
            $return['type'] = $matches[1];
            $return['description'] = trim(str_replace('*', '', $matches[2]));
            
            // 尝试解析返回值结构
            $return['structure'] = self::parseReturnStructure($return['description']);
        }
        
        return $return;
    }
    
    /**
     * 解析返回值结构
     * @param string $description 返回值描述
     * @return array|null 结构信息
     */
    protected static function parseReturnStructure($description) {
        // 检查是否包含结构描述
        if (preg_match('/结构[:：]\s*([^\n]+)/i', $description, $structMatch)) {
            $structStr = trim($structMatch[1]);
            
            // 简单解析键值对结构
            if (strpos($structStr, '{') !== false && strpos($structStr, '}') !== false) {
                try {
                    return json_decode($structStr, true);
                } catch (\Exception $e) {
                    // 解析失败，返回null
                }
            }
        }
        
        return null;
    }
    
    /**
     * 解析@example标签（请求/响应示例）
     * @param string $docBlock 文档块
     * @return array 示例列表
     */
    protected static function parseExamples($docBlock) {
        $examples = [];
        $pattern = '/@example\s+(\w+)\s*(.*?)(?=\*\s*@|\*\/)/s';
        
        if (preg_match_all($pattern, $docBlock, $matches, PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                $type = $match[1];
                $content = trim(str_replace('*', '', $match[2]));
                
                $examples[$type] = $content;
            }
        }
        
        return $examples;
    }
    
    /**
     * 解析@header标签（请求头）
     * @param string $docBlock 文档块
     * @return array 请求头列表
     */
    protected static function parseHeaders($docBlock) {
        $headers = [];
        $pattern = '/@header\s+(\w+)\s+(\w+)\s*(.*?)(?=\*\s*@|\*\/)/s';
        
        if (preg_match_all($pattern, $docBlock, $matches, PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                $headers[] = [
                    'name' => $match[2],
                    'type' => $match[1],
                    'description' => trim(str_replace('*', '', $match[3])),
                    'required' => true
                ];
            }
        }
        
        return $headers;
    }
    
    /**
     * 解析@validate标签（参数验证规则）
     * @param string $docBlock 文档块
     * @return array 验证规则
     */
    protected static function parseValidate($docBlock) {
        $validate = [];
        $pattern = '/@validate\s+(\S+)\s*(.*?)(?=\*\s*@|\*\/)/s';
        
        if (preg_match_all($pattern, $docBlock, $matches, PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                $validate[] = [
                    'rule' => $match[1],
                    'message' => trim(str_replace('*', '', $match[2]))
                ];
            }
        }
        
        return $validate;
    }
    
    /**
     * 解析@author标签
     * @param string $docBlock 文档块
     * @return string 作者信息
     */
    protected static function parseAuthor($docBlock) {
        $pattern = '/@author\s+(.*?)(?=\*\s*@|\*\/)/s';
        
        if (preg_match($pattern, $docBlock, $matches)) {
            return trim(str_replace('*', '', $matches[1]));
        }
        
        return '';
    }
    
    /**
     * 解析@since标签
     * @param string $docBlock 文档块
     * @return string 版本信息
     */
    protected static function parseSince($docBlock) {
        $pattern = '/@since\s+(.*?)(?=\*\s*@|\*\/)/s';
        
        if (preg_match($pattern, $docBlock, $matches)) {
            return trim(str_replace('*', '', $matches[1]));
        }
        
        return '';
    }
    
    /**
     * 生成示例响应
     * @param string $controllerFile 控制器文件
     * @param string $methodName 方法名称
     * @return array 示例响应
     */
    public static function generateExampleResponse($controllerFile, $methodName) {
        $docInfo = self::parseMethodDoc($controllerFile, $methodName);
        
        // 默认成功响应格式
        $successResponse = [
            'code' => 0,
            'msg' => 'success',
            'data' => null,
            'timestamp' => time()
        ];
        
        // 根据返回值类型生成示例数据
        if (!empty($docInfo['return']['type'])) {
            $successResponse['data'] = self::generateExampleData($docInfo['return']['type']);
        }
        
        return $successResponse;
    }
    
    /**
     * 生成示例数据
     * @param string $type 数据类型
     * @return mixed 示例数据
     */
    protected static function generateExampleData($type) {
        switch (strtolower($type)) {
            case 'int':
            case 'integer':
                return 1;
            case 'float':
            case 'double':
                return 1.0;
            case 'bool':
            case 'boolean':
                return true;
            case 'string':
                return '示例字符串';
            case 'array':
                return ['item1', 'item2'];
            case 'object':
                return (object)['key' => 'value'];
            case 'json':
                return ['id' => 1, 'name' => '示例数据'];
            default:
                // 如果是复杂类型，返回一个基本对象
                return (object)[];
        }
    }
}